home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS04.ADF
/
C
/
inputdev.c
< prev
next >
Wrap
C/C++ Source or Header
|
1985-10-30
|
11KB
|
292 lines
/* sample program for adding an input handler to the input stream */
/* note that this program also uses the CreateTimer, WaitTimer
* and DeleteTimer described in the timer device chapter.
*
* Rob Peck 10/1/85
*/
#define F1KEY 0x50
/* test program exits when the F1 key is touched. Steals all input
* events from Intuition when the program is active. Restores all
* to normal (including returning memory) when done
*/
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <exec/tasks.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <devices/inputevent.h>
SHORT noticedEventClass;
struct Port *inputDevPort;
struct IOStdReq *inputRequestBlock;
struct Interrupt handlerStuff;
struct InputEvent dummyEvent;
extern struct Port *CreatePort();
extern struct IOStdReq *CreateStdIO();
struct MemEntry me[10];
/* If we want the input handler itself to add anything to the
* input stream, we will have to keep track of any dynamically
* allocated memory so that we can later return it to the system.
* Other handlers can break any internal links the handler puts
* in before it passes the input events.
*/
char **evString[] = { "NULL", "RAWKEY", "RAWMOUSE", "EVENT",
"POINTERPOS", "UNDEFINED", "TIMER", "GADGETDOWN",
"GADGETUP", "REQUESTER", "MENULIST", "CLOSEWINDOW",
"SIZEWINDOW", "REFRESHWINDOW", "NEWPREFS", "DISKREMOVED",
"DISKINSERTED", "ACTIVEWINDOW", "INACTIVEWINDOW" };
struct InputEvent
*myhandler(ev, mydata)
struct InputEvent *ev; /* and a pointer to a list of events */
struct MemEntry *mydata[]; /* system will pass me a pointer to my
* own data space.
*/
{
/* demo version of program simply reports input events as
* its sees them; passes them on unchanged. Also, if there
* is a linked chain of input events, reports only the lead
* one in the chain, for simplicity.
*/
if(ev->ie_Class == IECLASS_TIMER) return(ev);
/* don't try to print timer events!!! they come every 1/10th sec. */
if(ev->ie_Code == F1KEY)
noticedEventClass = F1KEY;
/* provide a means of exiting this program, by pressing F1 */
else
noticedEventClass = ev->ie_Class;
/* There will be lots and lots of events coming through here;
* rather than make the system slow down because something
* is busy printing the previous event, lets just print what
* we find is current, and if we miss a few, so be it.
* Normally this loop would "handle" the event or perhaps
* add a new one to the stream. (At this level, the only
* events you should really be adding are mouse, rawkey or timer,
* because you are ahead of the intuition interpreter.)
* No printing is done in this loop (lets main() do it) because
* printf can't be done by anything less than a 'process'
*/
return(&dummyEvent);
/* pass on the pointer to the dummy event (most handlers would
* pass on a pointer to a changed or an unchanged stream) */
}
extern struct Task *FindTask();
struct Task *mytask;
LONG mysignal;
extern HandlerInterface();
struct IOStdReq *mytimerRequest;
extern struct IOStdReq *CreateTimer();
extern int WaitTimer();
extern int DeleteTimer();
main()
{
SHORT error;
/* init dummy event, this is what we will feed to other handlers
* while this handler is active */
dummyEvent.ie_Class = IECLASS_NULL; /* no event happened */
dummyEvent.ie_NextEvent = NULL; /* only this one in the chain */
inputDevPort = CreatePort(0,0); /* for input device */
if(inputDevPort == NULL) exit(-1); /* error during createport */
inputRequestBlock = CreateStdIO(inputDevPort);
if(inputRequestBlock == 0) { DeletePort(inputDevPort); exit(-2); }
/* error during createstdio */
mytimerRequest = CreateTimer();
if(mytimerRequest == NULL) exit(-3);
handlerStuff.is_Data = &me[0];
/* address of its data area */
handlerStuff.is_Code = HandlerInterface;
/* address of entry point to handler */
handlerStuff.is_Node.ln_Pri = 51;
/* set the priority one step higher than
* Intution, so that our handler enters
* the chain ahead of Intuition.
*/
error = OpenDevice("input.device",0,inputRequestBlock,0);
if(error == 0) printf("\nOpened the input device");
inputRequestBlock->io_Command = IND_ADDHANDLER;
inputRequestBlock->io_Data = &handlerStuff;
DoIO(inputRequestBlock);
for(;;) /* FOREVER */
{
WaitTimer(mytimerRequest, 0, 100000);
/* TRUE = wait; time = 1/10th second */
if(noticedEventClass == F1KEY) break; /* exit from forever */
if(noticedEventClass != 0)
{
printf("\nJust noticed %s class of event",
evString[noticedEventClass]);
noticedEventClass = 0;
}
}
/* Although this task sleeps (main loop), the handler is independently
* called by the input device.
*/
/* Following are discussion purposes only, no way to get here.
* Would have to provide a way to wake up in order to exit.
*/
inputRequestBlock->io_Command = IND_REMHANDLER;
inputRequestBlock->io_Data = &handlerStuff;
DoIO(inputRequestBlock);
CloseDevice(inputRequestBlock);
DeleteStdIO(inputRequestBlock);
DeletePort(inputDevPort);
DeleteTimer(mytimerRequest);
} /* end of main */
/* ******************************************************************** */
/* Exec Support Functions: CreateTimer, WaitTimer, DeleteTimer */
/*
/* CreateTimer() returns a pointer to an IOStdReq structure, set up
* for communications with the timer device. Returns NULL if it
* cannot allocate the timer or get enough memory or signals.
*
* WaitTimer(IOStdReq,seconds,microseconds) uses the communications
* block from CreateTimer(). It puts your task to sleep until the
* timer counts down at least this amount of time.
*
* SetTimer(IOStdReq,seconds,microseconds) returns a pointer to a port
* (copied from the IOStdReq) to which the timer returns the message
* block when the timeout has completed. It uses SendIO to transmit
* the IORequest. This means your task can go on to something else,
* then execute WaitPort(timerReplyPort), going to sleep until the
* timer has timed out. You will still have to do a GetMsg(timerReplyPort)
* after your task awakens, where with WaitTimer this is not necessary.
*
* DeleteTimer(IOStdReq) uses the block from CreateTimer() to free up
* memory and signal bits that have been allocated for this purpose.
*
* syntax Summary: struct IOStdReq *CreateTimer();
* int WaitTimer();
* struct Port *SetTimer();
* int DeleteTimer();
*/
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/devices.h>
#include <devices/timer.h>
#define SECONDS io_Actual
#define MICROSECONDS io_Length
/* redefine fields in IOStdReq so as to match requirements of a timeval */
extern struct Port *CreatePort();
extern struct IOStdReq *CreateStdIO();
struct IOStdReq
*CreateTimer() /* return a pointer to an IOStdReq if
* it was possible to allocate a new
* timer */
{
SHORT error;
struct Port *timerport;
struct IOStdReq *timermsg;
timerport = CreatePort(0,0);
if (timerport == NULL)
return(NULL); /* Error during CreatePort */
timermsg = CreateStdIO(timerport);
if (timermsg == NULL)
{
DeletePort(timerport);
return(NULL); /* Error during CreateStdIO */
}
error = OpenDevice(TIMERNAME, UNIT_MICROHZ, timermsg, 0);
if (error != 0)
{
DeleteStdIO(timermsg);
DeletePort(timerport);
return(NULL); /* Error during OpenDevice */
}
return(timermsg);
}
struct Port
*SetTimer(whichtimer,seconds,microseconds)
ULONG seconds,microseconds;
struct IOStdReq *whichtimer;
{
struct Port *tempPort;
tempPort = whichtimer->io_Message.mn_ReplyPort;
whichtimer->io_Command = TR_ADDREQUEST; /* add a new timer request */
whichtimer->SECONDS = seconds; /* seconds */
whichtimer->MICROSECONDS = microseconds; /* microseconds */
SendIO(whichtimer);
return(tempPort);
}
int
WaitTimer(whichtimer,seconds,microseconds)
ULONG seconds,microseconds;
struct IOStdReq *whichtimer;
{
whichtimer->io_Command = TR_ADDREQUEST; /* add a new timer request */
whichtimer->SECONDS = seconds; /* seconds */
whichtimer->MICROSECONDS = microseconds; /* microseconds */
DoIO(whichtimer);
return(0);
}
int
DeleteTimer(whichtimer)
struct IOStdReq *whichtimer;
{
struct Port *whichport;
whichport = whichtimer->io_Message.mn_ReplyPort;
DeleteStdIO(whichtimer);
DeletePort(whichport);
return(0);
}
*************************************************************************
* HandlerInterface()
*
* This code is needed to convert the calling sequence performed by
* the input.task for the input stream management into something
* that a C program can understand.
*
* This routine expects a pointer to an InputEvent in A0, a pointer
* to a data area in A1. These values are transferred to the stack
* in the order that a C program would need to find them. Since the
* actual handler is written in C, this works out fine.
XREF _myhandler
XDEF _HandlerInterface
_HandlerInterface:
MOVEM.L A0/A1,-(A7)
JSR _myhandler
ADDQ.L #8,A7
RTS
END